package com.gitee.wsl.compose.mvi

import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.currentRecomposeScope
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
//import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalFontFamilyResolver
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import com.gitee.wsl.compose.state.S
import com.gitee.wsl.struct.event.EventManager
import com.gitee.wsl.struct.event.EventsHandler
import com.gitee.wsl.struct.event.EventsHandlerImp
import kotlinx.coroutines.CoroutineScope

object View{
    //强制重组，类似View::invalidate()
    @Composable
    fun invalidate() = currentRecomposeScope.invalidate()

    /*@Composable
    fun context() = LocalContext.current*/

    //fun navController() = rememberNavController()

}


interface ViewSup<T: ViewScope<T>> {

    @Composable
    fun Config(modifier: Modifier,configFun:(scope: T, modifier:Modifier) -> Unit)

    @Composable
    fun Show()

    @Composable
    fun Hide()

}

 interface ViewScope<T: ViewScope<T>>{
    fun body(createFun:(@Composable (superScope: T,modifier: Modifier)->Unit))

    fun onStarted(block: () -> Unit)

    fun onDisposed(block: () -> Unit)

    fun onPause(block: () -> Unit)
}


abstract class AbstractView<T: ViewScope<T>>: ViewSup<T>, ViewScope<T>,EventManager {

    private lateinit var isVisable:MutableState<Boolean>

    var visableAnimator:Pair<EnterTransition?, ExitTransition?> = null to null

    var childCreateFun:(@Composable T.(modifier: Modifier)->Unit)? = null

    var onStarted: (() -> Unit)? = null

    var onPause: (() -> Unit)? = null

    var onDisposed: (() -> Unit)? = null

    lateinit var modifier:Modifier

    override val eventHandler: EventsHandler by lazy { EventsHandlerImp() }

    //管理当前获得焦点的文本框
    inline val focusManager @Composable
       get() = LocalFocusManager.current

    //用于请求焦点以显示软键盘
    lateinit var focusRequester : FocusRequester

    //它控制软键盘的显示和隐藏。
    inline val keyboardController @Composable
              get() = LocalSoftwareKeyboardController.current

    inline val fontResolver @Composable
              get() = LocalFontFamilyResolver.current
    inline val density @Composable
              get() = LocalDensity.current

    lateinit var scope : CoroutineScope

    @Composable
    override fun Config(modifier: Modifier, configFun:(scope: T, modifier:Modifier) -> Unit){
        isVisable = S.state(true)
        focusRequester = remember { FocusRequester() }
        scope = rememberCoroutineScope()
        this.modifier = modifier
        configFun(this as T ,modifier)
        OnCreate()
    }

    @Composable
    protected fun OnCreate() {
    }

    @Composable
    fun OnCreateChild(modifier: Modifier){
       childCreateFun?.invoke(this as T,modifier)
    }

   @Composable
   open fun OnCreateView(modifier: Modifier){
       OnCreateChild(modifier)
   }

    @Composable
    override fun Show() {
        OnCreateView(modifier)
        DisposableEffect(isVisable) {
            onStarted?.invoke()
            onDispose{
                onDisposed?.invoke()
            }
        }
        isVisable.value = true
    }

    @Composable
    override fun Hide() {
        isVisable.value = false
    }

    //scope
    override fun body(createFun:(@Composable (superScope: T,modifier: Modifier)->Unit)){
        childCreateFun = createFun
    }

    override fun onStarted(block: () -> Unit) {
        this.onStarted = block
    }

    override fun onDisposed(block: () -> Unit) {
        this.onDisposed = block
    }

    override fun onPause(block: () -> Unit) {
        this.onPause = block
    }


    //animator

}

